module uart_debug (
    input clk,
    input resetn,
    output reg reset_out,

    input uart_rx,
    output uart_tx,
    output reg [31:0] mem_addr,
    output reg [31:0] mem_wdata,
    output reg [ 3:0] mem_wstrb,
    output reg        mem_valid,
    input [31:0]      mem_rdata,
    input             mem_ready,
    output reg        halt_req,
    output reg        run_req,
    output reg        step_req,
    input             halt_signal,
    output reg [5:0]reg_addr,

    output reg dbg_reg_write_req,
    input dbg_reg_write_resp,
    output reg [31:0] dbg_reg_wdata,
    output reg [7:0] dbg_reg_raddr,
    output reg [7:0] dbg_reg_waddr,
    input [31:0]  dbg_reg_data_out,
    output reg [11:0] dbg_csr_reg_addr,
    output reg dbg_crs_reg_wr,
    input dbg_csr_we_resp,
    input [31:0] dbg_csr_data_out,
    output reg [31:0] dbg_csr_data_in,
    output reg cpu_reset_out
);
parameter CLK_FREQ=5000000;	//系统时钟频率
parameter UART_BPS=9600;		//波特率

wire [7:0] uart_rdata;
reg [7:0] uart_wdata;
reg uart_start;
wire uart_rxdone;
wire uart_txdone;
uart_recv
#(
	.CLK_FREQ	(CLK_FREQ),
	.UART_BPS	(UART_BPS)
)
u_uart_recv(
	.clk			(clk),
	.rst_n		(resetn),
	
	.uart_rxd	(uart_rx),
	.uart_data	(uart_rdata),
	.uart_done	(uart_rxdone)
);
uart_txd
#(
	.CLK_FREQ	(CLK_FREQ),
	.UART_BPS	(UART_BPS)
)
u_uart_txd(
	.clk			(clk),
	.rst_n		(resetn),

	.uart_txd	(uart_tx),
	.uart_en		(uart_start),

	.uart_data	(uart_wdata),
    .uart_tx_done (uart_txdone)
	);
reg uart_rxdone_r0;
wire uart_rxdone_pos;
always @(posedge clk) begin
    uart_rxdone_r0 <= uart_rxdone;
end
assign uart_rxdone_pos = uart_rxdone &(~uart_rxdone_r0);

reg [1:0] uart_state;
reg [3:0] uart_cnt;
reg uart_send_state;
parameter uart_send = 1'b0;
parameter uart_tx_wait = 1'b1;

parameter uart_idle = 2'b00;
parameter uart_parse = 2'b01;
parameter uart_work = 2'b10;
parameter uart_resp = 2'b11;
reg [7:0] control;
reg [31:0] response_data;
always@(posedge clk or negedge resetn) begin
    if(!resetn) begin
        reset_out <= 1'b0;
        uart_wdata <= 8'h0;
        uart_state <= uart_idle;
        uart_cnt <= 4'h0;
        uart_start <= 1'b0;
        uart_send_state <= uart_send;
        halt_req <= 1'b0;
        run_req <= 1'b0;
        step_req <= 1'b0;
        dbg_crs_reg_wr <= 1'b0;
        dbg_reg_write_req <= 1'b0;
        cpu_reset_out <= 1'b1;
    end
    else begin
        cpu_reset_out <= 1'b1;
        if(halt_signal) begin
            halt_req <= 1'b0;
        end
        else begin
            step_req <= 1'b0;
        end
        if(dbg_csr_we_resp) begin
            dbg_crs_reg_wr <= 1'b0;
        end
        if(dbg_reg_write_resp) begin
            dbg_reg_write_req <= 1'b0;
        end
        run_req <= 1'b0;
        mem_valid <= 1'b0;
        mem_wstrb <= 4'b0;
        case(uart_state)
        uart_idle:begin
            reset_out <= 1'b1;
            uart_cnt <= 4'h0;
            uart_start <= 1'b0;
            if(uart_rxdone_pos) begin
                
                control <= uart_rdata;//
                uart_state <= uart_parse;
            end
        end
        uart_parse:begin
            casex(control)
            8'h68:begin//查询cpu状态
                uart_state <= uart_resp;
                uart_send_state <= uart_tx_wait;
                uart_start <= 1'b1;
                uart_wdata <= {7'd0,halt_signal};
            end
            8'h69:begin
                if(halt_signal) begin
                    step_req <= 1'b1;
                end
                uart_state <= uart_resp;
                uart_send_state <= uart_tx_wait;
                uart_start <= 1'b1;
                uart_wdata <= 8'h69;
            end
            8'h70:begin
                if(!halt_signal)begin
                    halt_req <= 1'b1;
                end
                uart_state <= uart_resp;
                uart_send_state <= uart_tx_wait;
                uart_start <= 1'b1;
                uart_wdata <= 8'h70;
            end
            8'h71:begin
                run_req <= 1'b1;
                uart_state <= uart_resp;
                uart_send_state <= uart_tx_wait;
                uart_start <= 1'b1;
                uart_wdata <= 8'h71;
            end
            8'h72:begin//读cpu 通用寄存器
                uart_cnt <= 4'h0;
                if(uart_rxdone_pos) begin
                    dbg_reg_raddr <= uart_rdata;
                    uart_state <= uart_work;
                    uart_cnt <= 4'h0;  
                end
                else begin
                    uart_state <= uart_parse;
                end
            end
            8'h73:begin//写cpu 通用寄存器
                if(uart_cnt == (4'd5)) begin
                    uart_state <= uart_work;
                end
                else begin
                    uart_state <= uart_parse;
                end
                if(uart_rxdone_pos) begin
                    if(uart_cnt < 4'd1) begin
                        dbg_reg_waddr <= uart_rdata;
                    end
                    else begin
                        dbg_reg_wdata <= {dbg_reg_wdata[23:0],uart_rdata};
                    end
                    uart_cnt <= uart_cnt + 1'b1;  
                end
                else begin
                    uart_cnt <= uart_cnt;
                    dbg_reg_waddr <= dbg_reg_waddr;
                    dbg_reg_wdata <= dbg_reg_wdata;
                end
            end
            8'h74:begin//读cpu csr寄存器
                if(uart_cnt == (4'd2)) begin
                    uart_cnt <= 4'd0;
                    uart_state <= uart_work;
                end
                else begin
                    uart_state <= uart_parse;
                end
                if(uart_rxdone_pos) begin
                    dbg_csr_reg_addr <= {dbg_csr_reg_addr[3:0],uart_rdata};
                    uart_cnt <= uart_cnt + 1'b1;  
                end
                else begin
                    uart_cnt <= uart_cnt;
                    dbg_csr_reg_addr <= dbg_csr_reg_addr;
                end
            end
            8'h75:begin//写cpu csr寄存器
                if(uart_cnt == (4'd6)) begin
                    uart_state <= uart_work;
                end
                else begin
                    uart_state <= uart_parse;
                end
                if(uart_rxdone_pos) begin
                    if(uart_cnt < 4'd2) begin
                        dbg_csr_reg_addr <= {dbg_csr_reg_addr[3:0],uart_rdata};
                    end
                    else begin
                        dbg_csr_data_in <= {dbg_csr_data_in[23:0],uart_rdata};
                    end
                    uart_cnt <= uart_cnt + 1'b1;  
                end
                else begin
                    uart_cnt <= uart_cnt;
                    dbg_csr_reg_addr <= dbg_csr_reg_addr;
                    dbg_csr_data_in <= dbg_csr_data_in;
                end
            end
            8'hfe:begin//状态机复位
                uart_wdata <= 8'hfe;
                uart_start <= 1'b1;
                reset_out <= 1'b0;
                uart_cnt <= uart_cnt + 1'b1;
                uart_state <= uart_idle;
                if(uart_cnt == 4'h4) begin
                    uart_state <= uart_idle;
                end
                else begin
                    uart_state <= uart_state;
                end
            end
            8'hf0:begin//外设复位
                uart_wdata <= 8'hf0;
                uart_start <= 1'b1;
                reset_out <= 1'b0;
                uart_cnt <= uart_cnt + 1'b1;
                uart_state <= uart_idle;
                cpu_reset_out <= 1'b0;
                if(uart_cnt == 4'h4) begin
                    uart_state <= uart_idle;
                end
                else begin
                    uart_state <= uart_state;
                end
            end
            8'h8x:begin
                if(uart_cnt == 4'd4) begin
                        uart_state <= uart_work;
                end
                else begin
                    uart_state <= uart_parse;
                end
                if(uart_rxdone_pos) begin
                    mem_addr <= {mem_addr[23:0],uart_rdata};
                    uart_cnt <= uart_cnt + 1'b1;  
                end
                else begin
                    uart_cnt <= uart_cnt;
                    mem_addr <= mem_addr;
                    
                end
            end
            8'h9x:begin
                if(uart_cnt == (4'd4 + control[3:0])) begin
                    uart_state <= uart_work;
                end
                else begin
                    uart_state <= uart_parse;
                end
                if(uart_rxdone_pos) begin
                    if(uart_cnt < 4'd4) begin
                        mem_addr <= {mem_addr[23:0],uart_rdata};
                    end
                    else begin
                        mem_wdata <= {mem_wdata[23:0],uart_rdata};
                    end
                    uart_cnt <= uart_cnt + 1'b1;  
                end
                else begin
                    uart_cnt <= uart_cnt;
                    mem_addr <= mem_addr;
                end
            end
            default:uart_state <= uart_idle;
            endcase
        end
        uart_work:begin
            casex(control)
            8'h8x:begin
                mem_valid <= 1'b1;
                mem_wstrb <= 4'b0;
                if(mem_ready)begin
                    mem_valid <= 1'b0;
                    mem_wstrb <= 4'b0;
                    uart_state <= uart_resp;
                    if(control[3:0] == 2'd1) begin
                        case(mem_addr[2:0])
                        2'd0:begin
                            response_data <= {4{mem_rdata[7:0]}};
                        end
                        2'd1:begin
                            response_data <= {4{mem_rdata[15:8]}};
                        end
                        2'd2:begin
                            response_data <= {4{mem_rdata[23:16]}};
                        end
                        2'd3:begin
                            response_data <= {4{mem_rdata[31:24]}};
                        end
                        endcase
                    end
                    else if(control[3:0] == 2'd2) begin
                        if(mem_addr[1]) begin
                            response_data <= {2{mem_rdata[31:16]}};
                        end
                        else begin
                            response_data <= {2{mem_rdata[15:0]}};
                        end
                    end
                    else begin
                        response_data <= mem_rdata;
                    end
                    uart_cnt <= 4'h0;
                    uart_send_state <= uart_tx_wait;
                end
                else begin
                    uart_state <= uart_state;
                end
            end
            8'h72:begin//读cpu 通用寄存器
                response_data <= dbg_reg_data_out;
                uart_cnt <= uart_cnt + 1'b1;
                uart_send_state <= uart_tx_wait;
                if( uart_cnt > 1'b1) begin
                    uart_state <= uart_resp;
                    uart_cnt <= 4'h0;
                end
                else begin
                    uart_state <= uart_state;
                end
            end
            8'h73:begin//写CPU通用寄存器
                dbg_reg_write_req <= 1'b1;
                uart_state <= uart_idle;
                uart_wdata <= 8'h73;
                uart_start <= 1'b1;
            end
            8'h74:begin//读cpu csr寄存器
                response_data <= dbg_csr_data_out;
                uart_cnt <= uart_cnt + 1'b1;
                uart_send_state <= uart_tx_wait;
                if( uart_cnt > 1'b1) begin
                    uart_state <= uart_resp;
                    uart_cnt <= 4'h0;
                end
                else begin
                    uart_state <= uart_state;
                end
            end
            8'h75:begin//写cpu csr寄存器
                dbg_crs_reg_wr <= 1'b1;
                uart_wdata <= 8'h75;
                uart_start <= 1'b1;
                uart_state <= uart_idle;
            end
            8'h9x:begin
                if((control[3:0] == 4'h1) || ((control[3:0] == 4'h2)&&(mem_addr[0] == 1'b0))
                || ((control[3:0] == 4'h4)&&(mem_addr[1:0] == 2'b0))) begin
                    uart_state <= uart_state;
                    case(control[3:0])
                    4'h1:begin
                        mem_valid <= 1'b1;
                        mem_wdata <= {4{mem_wdata[7:0]}};
                        case(mem_addr[1:0])
                        2'b00: begin
                            mem_wstrb <= 4'b0001;
                        end
                        2'b01: begin
                            mem_wstrb <= 4'b0010;
                        end
                        2'b10: begin
                            mem_wstrb <= 4'b0100;
                        end
                        default: begin
                            mem_wstrb <= 4'b1000;
                        end
                        endcase
                    end
                    4'h2:begin
                        mem_valid <= 1'b1;
                        mem_wdata <= {2{mem_wdata[15:0]}};
                        if (mem_addr[1:0] == 2'b00) begin
                            mem_wstrb <= 4'b0011;
                        end else begin
                            mem_wstrb <= 4'b1100;
                        end
                    end
                    4'h4:begin
                        mem_valid <= 1'b1;
                        mem_wstrb <= 4'b1111;
                        mem_wdata <= mem_wdata;
                    end
                    endcase
                    if(mem_ready)begin
                        uart_wdata <= control;
                        uart_start <= 1'b1;
                        mem_valid <= 1'b0;
                        mem_wstrb <= 4'b0;
                        uart_state <= uart_idle;
                        uart_cnt <= 4'h0;
                    end
                end
                else begin
                    uart_state <= uart_idle;
                end
            end
            default:uart_state <= uart_idle;
            endcase
            
        end
        uart_resp:begin
            casex(control)
            8'h68:begin//查询cpu状态
                uart_start <= 1'b0;
                if(uart_txdone)begin
                    uart_state <= uart_idle;
                    uart_cnt <= 4'h0;
                end
            end
            8'h69:begin
                uart_start <= 1'b0;
                if(uart_txdone)begin
                    uart_state <= uart_idle;
                    uart_cnt <= 4'h0;
                end
            end
            8'h70:begin
                uart_start <= 1'b0;
                if(uart_txdone)begin
                    uart_state <= uart_idle;
                    uart_cnt <= 4'h0;
                end
            end
            8'h71:begin
                uart_start <= 1'b0;
                if(uart_txdone)begin
                    uart_state <= uart_idle;
                    uart_cnt <= 4'h0;
                end
            end
            8'h72:begin
                if(uart_cnt < 4'h4) begin
                    uart_state <= uart_state;
                end
                else begin
                    uart_state <= uart_idle;
                end
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_wdata <= response_data[31:24];
                        response_data <= {response_data[23:0],8'h0};
                        uart_send_state <= uart_send;
                        uart_cnt <= uart_cnt + 1'b1;
                    end
                end
                endcase
            end
            8'h74:begin//读cpu csr寄存器
                if(uart_cnt < 4'h4) begin
                    uart_state <= uart_state;
                end
                else begin
                    uart_state <= uart_idle;
                end
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_wdata <= response_data[31:24];
                        response_data <= {response_data[23:0],8'h0};
                        uart_send_state <= uart_send;
                        uart_cnt <= uart_cnt + 1'b1;
                    end
                end
                endcase
            end
            8'h8x:begin
                if(uart_cnt < control[3:0]) begin
                    uart_state <= uart_state;
                end
                else begin
                    uart_state <= uart_idle;
                end
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_wdata <= response_data[31:24];
                        response_data <= {response_data[23:0],8'h0};
                        uart_send_state <= uart_send;
                        uart_cnt <= uart_cnt + 1'b1;
                    end
                end
                endcase
            end
            endcase
        end
        endcase
    end
end    

endmodule